package www.wen.com.common.lib.util

import android.content.ContentResolver
import android.content.Context
import android.graphics.Bitmap
import android.net.Uri
import android.os.Environment
import android.provider.MediaStore
import android.util.Log
import com.orhanobut.logger.Logger
import www.wen.com.common.lib.app.BaseApplication.Companion.CONTEXT
import www.wen.com.common.lib.extension.toast
import java.io.*


/**
 * @author WEN
 * @Description:
 * @date 2021/2/3 10:01
 */
object FileUtils {

    private const val TAG = "FileUtils"

    /**
     * 保存图片
     * @param bitmap 图片
     * @param name 存储名字
     * @param path 存储路径
     * @param isCovered 如果存在同名文件则删除
     */
    @Throws(IllegalStateException::class)
    fun saveBitmap(
        bitmap: Bitmap?,
        name: String,
        path: String,
        isCovered: Boolean = true,
        context: Context = CONTEXT
    ): File? {
        (checkNotNull(bitmap))
        var outStream: FileOutputStream? = null
        var bitmapFile: File? = null
        try {
            bitmapFile = getDeviceExternalFilesDir(path, name, context)

            if (isCovered && bitmapFile.isFile && bitmapFile.exists()) {
                bitmapFile.delete()
            }

            outStream = FileOutputStream(bitmapFile)
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream)
        } catch (e: Exception) {
            Logger.i("图片存储异常 = ${e.message}")
            toast("图片保存失败")
        } finally {
            outStream?.flush()
            outStream?.close()
            return bitmapFile
        }
    }


    fun getDeviceExternalFilesDir(
        path: String,
        fileName: String,
        context: Context = CONTEXT
    ): File {
        val parentFile: File? = context.getExternalFilesDir(path)
        var childFile = File("")
        if (parentFile != null && Environment.getExternalStorageState(parentFile) == Environment.MEDIA_MOUNTED) {
            if (!parentFile.exists()) {
                val isMake = parentFile.mkdirs()
                if (isMake) {
                    childFile = File(parentFile, fileName)
                    Log.i(TAG, "外置路径已创建, 外置路径: $parentFile")
                } else {
                    Log.i(TAG, "外置路径创建失败")
                    // TODO: 2021/1/23 异常上报框架
                    throw IllegalArgumentException("可能因为手机SD卡没有挂载导致无法创建文件夹")
                }
            } else {
                Log.i(TAG, "外置路径已存在不需要创建, 外置路径: $parentFile")
                childFile = File(parentFile, fileName)
            }
        } else {
            Log.i(TAG, "外置路径可能因为SD没有挂载导致无法创建")
        }

        if (parentFile == null) {
            // TODO: 2021/1/23 异常上报框架
            throw IllegalArgumentException("可能因为手机SD卡没有挂载导致无法创建文件夹")
        } else {
            Logger.i("文件名字,childFile = ${childFile.name}")
            return childFile
        }
    }


    //获取指定目录下的所有非文件夹的名称
    fun getFileListInTheFolder(
        path: String,
        context: Context = CONTEXT,
        isAssignSuffix: Boolean = false,
        suffix: String = ""
    ): Array<File> {
        val parentFile: File? = context.getExternalFilesDir(path)
        if (parentFile != null && Environment.getExternalStorageState(parentFile) == Environment.MEDIA_MOUNTED) {
            return if (!parentFile.exists()) {
                val isMake = parentFile.mkdirs()
                if (isMake) {
                    parentFile.listFiles()
                } else {
                    throw IllegalArgumentException("可能因为手机SD卡没有挂载导致无法创建文件夹")
                }
            } else {
                //文件夹存在获取所有文件
                return try {
                    checkNotNull(parentFile.listFiles())
                    if (isAssignSuffix) {
                        if (suffix.isNotEmpty()) {
                            val files = mutableListOf<File>()
                            parentFile.listFiles()!!.forEach {
                                if (it.name.endsWith(suffix)) {
                                    files.add(it)
                                }
                            }
                            files.toTypedArray()
                        } else {
                            parentFile.listFiles()!!
                        }
                    } else {
                        parentFile.listFiles()!!
                    }

                } catch (e: IllegalStateException) {
                    arrayOf()
                }
            }
        } else {
            throw IllegalArgumentException("可能因为手机SD卡没有挂载导致无法创建文件夹")
        }
    }


    fun getSaveFile(context: Context = CONTEXT): File {
        return File(context.filesDir, "pic.jpg")
    }

    /**
     * 获取真实路径
     *
     * @param context
     */
    fun getFileFromUri(uri: Uri?, savePath: String): String? {
        return if (uri == null) {
            null
        } else when (uri.scheme) {
            ContentResolver.SCHEME_CONTENT ->                 //Android7.0之后的uri content:// URI
                getFilePathFromContentUri(uri, savePath)
            ContentResolver.SCHEME_FILE ->                 //Android7.0之前的uri file://
                File(uri.path).absolutePath
            else -> File(uri.path).absolutePath
        }
    }


    /**
     * 从uri获取path
     *
     * @param uri content://media/external/file/109009
     *
     *
     * FileProvider适配
     * content://com.tencent.mobileqq.fileprovider/external_files/storage/emulated/0/Tencent/QQfile_recv/
     * content://com.tencent.mm.external.fileprovider/external/tencent/MicroMsg/Download/
     */
    private fun getFilePathFromContentUri(
        uri: Uri,
        savePath: String,
        context: Context = CONTEXT
    ): String? {
        var data: String? = null
        val filePathColumn = arrayOf(
            MediaStore.MediaColumns.DATA,
            MediaStore.MediaColumns.DISPLAY_NAME
        )
        val cursor = context.contentResolver.query(uri, filePathColumn, null, null, null)
        if (null != cursor) {
            if (cursor.moveToFirst()) {
                val index = cursor.getColumnIndex(MediaStore.MediaColumns.DATA)
                data = if (index > -1) {
                    cursor.getString(index)
                } else {
                    val nameIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME)
                    val fileName = cursor.getString(nameIndex)
                    getPathFromInputStreamUri(uri, fileName, savePath)
                }
            }
            cursor.close()
        }
        return data
    }

    /**
     * 用流拷贝文件一份到自己APP私有目录下
     *
     * @param context
     * @param uri
     * @param fileName
     */
    private fun getPathFromInputStreamUri(
        uri: Uri,
        fileName: String,
        savePath: String,
        context: Context = CONTEXT
    ): String? {
        var inputStream: InputStream? = null
        var filePath: String? = null
        if (uri.authority != null) {
            try {
                inputStream = context.contentResolver.openInputStream(uri)
                val file = createTemporalFileFrom(inputStream, fileName, savePath)
                filePath = file!!.path
            } catch (e: java.lang.Exception) {
            } finally {
                try {
                    inputStream?.close()
                } catch (e: java.lang.Exception) {
                }
            }
        }
        return filePath
    }

    @Throws(IOException::class)
    private fun createTemporalFileFrom(
        inputStream: InputStream?,
        fileName: String,
        savePath: String
    ): File? {
        var targetFile: File? = null
        if (inputStream != null) {
            var read: Int
            val buffer = ByteArray(8 * 1024)
            //自己定义拷贝文件路径
            targetFile = getDeviceExternalFilesDir(savePath, fileName)
            if (targetFile.exists()) {
                targetFile.delete()
            }
            val outputStream: OutputStream = FileOutputStream(targetFile)
            while (inputStream.read(buffer).also { read = it } != -1) {
                outputStream.write(buffer, 0, read)
            }
            outputStream.flush()
            try {
                outputStream.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
        return targetFile
    }

    @JvmStatic
    fun copy(fileInputStream: FileInputStream, outputStream: OutputStream) {
        try {
            val buffer = ByteArray(1024)
            var len: Int
            while (fileInputStream.read(buffer).also { len = it } > 0) {
                outputStream.write(buffer, 0, len)
            }
        } catch (e: Exception) {

        }
    }

}